package com.dbiservices.dbiworker.model.plugin;

import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.log4j.Logger;

public class PluginLoader {
	
	private static Logger log = Logger.getLogger(PluginLoader.class);

	public File[] loadPluginFolders(String pluginFolderName){
		File pluginFolderFile = new File(pluginFolderName);
		
		FileFilter folderFilter = new FileFilter() {
			
			@Override
			public boolean accept(File f) {
				return f.isDirectory();
			}
		};
		
		File[] pluginFolders = pluginFolderFile.listFiles(folderFilter);
		
		return pluginFolders;
	}
	
	public ArrayList<Plugin> load(File[] pluginFolders) throws JAXBException, MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException{
		ArrayList<Plugin> plugins = new ArrayList<Plugin>();
		for (File pluginFolder : pluginFolders){
			File pluginXml = new File(pluginFolder, "plugin.xml");
			if (pluginXml.exists()){
				PluginInfo pluginInfo = this.parsePluginInfo(pluginXml);
				if(pluginInfo.isEnabled()){
					Plugin plugin = this.loadPlugin(pluginInfo,pluginFolder);
					plugins.add(plugin);
					
				}
			}else{
				log.error("No plugin.xml file found at path "+pluginXml.getAbsolutePath());
			}
		}
		return plugins;
	}

	private Plugin loadPlugin(PluginInfo pluginInfo, File pluginFolder) throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
		FileFilter filterJars = new FileFilter() {
			
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".jar");
			}
		};
		File[] jars = pluginFolder.listFiles(filterJars);
		URL[] urls = new URL[jars.length];
		for (int i = 0 ; i < jars.length ; ++i){
			urls[i] = jars[i].toURI().toURL();
		}
		
		ClassLoader loader = URLClassLoader.newInstance(
			    urls,
			    PluginLoader.class.getClassLoader()
			);
		Class<?> p = Class.forName(pluginInfo.getPluginClass(), true, loader);
		return (Plugin)p.newInstance();
	}

	private PluginInfo parsePluginInfo(File pluginXml) throws JAXBException {
		JAXBContext jaxbContext = JAXBContext.newInstance(PluginInfo.class);
		Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
		PluginInfo pi = (PluginInfo) jaxbUnmarshaller.unmarshal(pluginXml);
		return pi;
	}
}
